package fr.asip.cps3.exemple.modele.traitements.fonctionsPKCS11.signature;

import org.apache.log4j.Logger;

import iaik.pkcs.pkcs11.wrapper.CK_MECHANISM;
import iaik.pkcs.pkcs11.wrapper.PKCS11;
import iaik.pkcs.pkcs11.wrapper.PKCS11Exception;
import fr.asip.cps3.exemple.modele.exceptions.ExceptionProgrammeExemple;
import fr.asip.cps3.exemple.modele.exceptions.ExceptionTraitement;
import fr.asip.cps3.exemple.modele.resultats.Resultat;
import fr.asip.cps3.exemple.modele.resultats.ResultatSignatureMessage;
import fr.asip.cps3.exemple.modele.traitements.util.TraitementsUtil;

/**
 * Classe de traitement : Génération de la signature d'un message
 *
 */
public class GenererSignatureMessage{
	
	
	/**
	 * Le loggeur
	 */
	private static Logger log = Logger.getLogger(GenererSignatureMessage.class);
	
	/**
	 * Renvoie le résultat de l'opération
	 * @param librairie Librairie PKCS#11 à utiliser
	 * @param idSession Identifiant de la session
	 * @param typeAlgo Type de l'algorithme
	 * @param idCle Identifiant de la clé privée
	 * @param message Message à signer
	 * @return Résultat de l'opération
	 * @throws ExceptionTraitement
	 */
	public static Resultat traitementP11(PKCS11 librairie, long idSession, long typeAlgo, long cle, char[] message) throws ExceptionTraitement {

		try {
		
			if(librairie != null) {
				
				if(message != null) {
		
					CK_MECHANISM algo = new CK_MECHANISM();
					algo.mechanism=typeAlgo;
					
					ResultatSignatureMessage resultat = new ResultatSignatureMessage("Génération de la signature d'un message avec "+TraitementsUtil.getNomAlgo(typeAlgo)+" (Initialisation (C_SignInit))","Génération de la signature d'un message avec "+TraitementsUtil.getNomAlgo(typeAlgo)+" (Génération (C_Sign))");
					
					if(message != null) {
						
						byte[] signature = null;
						boolean erreurSurvenue = false;
						
						// Traitements à tester
						try {
							
							//# INIT #//
							librairie.C_SignInit(idSession, algo, cle);
							
						} catch (PKCS11Exception e) {
							
							log.info("Operation echouee : "+TraitementsUtil.retranscritCodeRetour(e.getErrorCode()));
							resultat.setCodeRetour(e.getErrorCode());
							erreurSurvenue = true;
							resultat.setCodeRetour2(TraitementsUtil.AUCUN_CODE_RETOUR);
							resultat.appendOperation2(" NON EXECUTEE!");
							
						}
						try {
							
							//# GENERATION DE LA SIGNATURE #//
							if(!erreurSurvenue) {
								signature = librairie.C_Sign(idSession,new String(message).getBytes());
								if(signature != null)
									resultat.setSignature(TraitementsUtil.getHexadecimal(signature,16));
							}
							
						} catch (PKCS11Exception e) {
							
							log.info("Operation echouee : "+TraitementsUtil.retranscritCodeRetour(e.getErrorCode()));
							resultat.setCodeRetour2(e.getErrorCode());
							
						}
					}
			
					return resultat;
					
				} else {
				
					// Si le message est null il est impossible de réaliser l'opération
					log.error("Le message est nul");
					throw new ExceptionTraitement(ExceptionProgrammeExemple.TYPE_TRAITEMENT_SIGNATURES_MESSAGE, "Le message est nul");				
				
				}
				
			} else {
				
				// Si la librairie est nulle il est impossible de réaliser l'opération
				log.error("La librairie est nulle");
				throw new ExceptionTraitement(ExceptionProgrammeExemple.TYPE_TRAITEMENT_SIGNATURES_MESSAGE, "La librairie est nulle");
				
			}
				
		} catch (Throwable t) {
			
			// Si une erreur Traitement a été rencontrée on lève l'exception
			if(t instanceof ExceptionTraitement)
				throw (ExceptionTraitement)t;
			
			// Si une erreur inattendue est survenue on la logue et on la lève
			log.error("Une erreur inattendue est survenue : "+ExceptionProgrammeExemple.getStacktrace(t));
			throw new ExceptionTraitement(ExceptionProgrammeExemple.TYPE_TRAITEMENT_SIGNATURES_MESSAGE, "Une erreur inattendue est survenue");
			
		}
		
	}
	
}
